package muhnes.sizoo.dal;

import java.util.List;
import muhnes.sizoo.HibernateUtilZoologia;
import muhnes.sizoo.modelo.Animal;
import muhnes.sizoo.modelo.Especimen;
import muhnes.sizoo.modelo.Municipio;
import muhnes.sizoo.modelo.Recoleccion;
import org.hibernate.Query;
import org.hibernate.Session;

/**
 * Clase que contiene las metodos que fueron definifos en AnimalDao
 * @author Ricardo Orellana
 */
public class AnimalDaoImpl extends GenericoDAO< Animal, Integer >  
                           implements AnimalDao {
     
    public AnimalDaoImpl() {
        super( HibernateUtilZoologia.getSessionFactory() );
    }

    @Override
    protected Class<?> getClaseEntidad() {
        return Animal.class;
    }

    @Override
    public List<Animal> buscarAves() {        
        return buscarAnimalPorTipo(1);
    }

    @Override
    public List<Animal> buscarMamiferos() {
        return buscarAnimalPorTipo(4);
    }

    @Override
    public List<Animal> buscarPeces() {
        return buscarAnimalPorTipo(2);
    }

    @Override
    public List<Animal> buscarInsectos() {
        return buscarAnimalPorTipo(3);
    }

    @Override
    public List<Animal> buscarReptiles() { 
        return buscarAnimalPorTipo(5);
    }

    @Override
    public List<Animal> buscarMoluscos() {
        return buscarAnimalPorTipo(6);
    }

    /**
     * Método que devuelve una lista de municipios 
     *  
     */
    @Override
    public List<Municipio> buscarMunicipiosAsociados(Animal animal) {
       Session sesion = fabricaSesion.getCurrentSession();
       String hql = "select distinct municipio " +
                    "from Animal animal, " +
                    "Especimen especimen, " +
                    "Recoleccion recoleccion, " +
                    "Nacional nacional, " +
                    "Zona zona, " +
                    "Municipio municipio " +
                    "where especimen.animal.codigoanimal = :codigo " +
                    "and especimen.recoleccion.codigorecoleccion = recoleccion.codigorecoleccion " +
                    "and recoleccion.codigorecoleccion = nacional.codigorecoleccion " +
                    "and nacional.zona.codigozona = zona.codigozona " +
                    "and zona.municipio.codigomunicipio = municipio.codigomunicipio order by municipio desc";
        Query consulta = sesion.createQuery(hql);
        consulta.setParameter("codigo", animal.getCodigoanimal());
        List< Municipio > animales = consulta.list();
        return animales;
    }
    
    /**
     * Método que devuelve una lista de recolecciones asociadas a los especimenes de animales
     * 
     */
    @Override
    public List<Recoleccion> buscarRecoleccionesAsociadas(Animal animal) {
       Session sesion = fabricaSesion.getCurrentSession();
       String hql = "select recoleccion " +
                    "from Animal animal, " +
                    "Especimen especimen, " +
                    "Recoleccion recoleccion " +
                    "where animal.codigoanimal = :codigo " +
                    "and animal.codigoanimal = especimen.animal.codigoanimal " +
                    "and especimen.recoleccion.codigorecoleccion = recoleccion.codigorecoleccion";
       Query consulta = sesion.createQuery(hql);
       consulta.setParameter("codigo", animal.getCodigoanimal());
       List<Recoleccion> recolecciones = consulta.list();
       return recolecciones;
    }

    /**
     * Método que devuelve una lista de animales que estan en estado de revisión.
     * 
     */
    @Override
    public List<Animal> buscarAnimalesEnRevision() {
        Session sesion = fabricaSesion.getCurrentSession();
        String hql = "from Animal where upper(estado) = 'REVISION'";
        Query consulta = sesion.createQuery( hql );
        List< Animal > animales = consulta.list();
        return animales;
    }
    
    /**
     * Método que devuelve una lista de tipo de animales
     * 
     */
    /*private List<Animal> buscarAnimalPorTipo ( char tipo ) {        
        Session sesion = fabricaSesion.getCurrentSession();
        String hql = "from Animal " +
                     "where (grupo = '" + Character.toLowerCase(tipo) + "' " +
                     "or grupo = '" + Character.toUpperCase(tipo) + "') " +
                     "and upper(estado) = 'ACTIVO'";
        Query consulta = sesion.createQuery(hql);
        List<Animal> animales = consulta.list();
        return animales;
    }*/
    private List<Animal> buscarAnimalPorTipo ( int tipo ) {        
        Session sesion = fabricaSesion.getCurrentSession();
        String hql = "from Animal " +
                     "where codigogrupo = " + tipo + " " +
                     "and upper(estado) = 'ACTIVO'";
        Query consulta = sesion.createQuery(hql);
        List<Animal> animales = consulta.list();
        return animales;
    }
    
    /**
     * Método que verifica que los animales sean unicos.
     * 
     */
    @Override
    public boolean verificarUnicidad(Animal entidad) {
        Session sesion = fabricaSesion.getCurrentSession();        
        String hql = "from Animal " +
                     "where codigoanimal != :codigo " +
                     "and upper(nombrecientifico) = :nombrecientifico";
        Query consulta = sesion.createQuery( hql );
        consulta.setParameter("codigo", entidad.getCodigoanimal());
        consulta.setParameter("nombrecientifico", entidad.getNombrecientifico().toUpperCase());
        return consulta.uniqueResult() != null ? true : false;
    }

    /**
     * Método que verifica que la entidad sea independiente de las demas entidades.
     * 
     */
    @Override
    public boolean verificarDependencia (Animal entidad) {
        Session sesion = fabricaSesion.getCurrentSession();        
        String hql = "from Especimen where animal.codigoanimal = :codigo";
        Query consulta = sesion.createQuery( hql );
        consulta.setParameter("codigo",entidad.getCodigoanimal());
        return !consulta.list().isEmpty();
    }

    /**
     * Metodo que devuelve una lista de fotos de los especimenes por municipio
     * 
     */
    @Override
    public List<Especimen> buscarFoto(Animal animal, Municipio municipio){
         Session sesion = fabricaSesion.getCurrentSession();
       String hql = "select distinct especimen " +
                    "from Animal animal, " +
                    "Especimen especimen, " +
                    "Recoleccion recoleccion, " +
                    "Nacional nacional, " +
                    "Zona zona, " +
                    "Municipio municipio " +
                    "where especimen.animal.codigoanimal = :codigo " +
                    "and municipio.codigomunicipio = :municipio " +
                    "and especimen.recoleccion.codigorecoleccion = recoleccion.codigorecoleccion " +
                    "and recoleccion.codigorecoleccion = nacional.codigorecoleccion " +
                    "and nacional.zona.codigozona = zona.codigozona " +
                    "and zona.municipio.codigomunicipio = municipio.codigomunicipio";
       
        Query consulta = sesion.createQuery(hql);
        consulta.setParameter("codigo", animal.getCodigoanimal());
        consulta.setParameter( "municipio", municipio.getCodigomunicipio());
        List<Especimen> especimenes = consulta.list();
          
        return especimenes;
    }
    
    
    /**
     * Metodo que devuelve una lista de fotos de los especimenes por recoleccion
     * 
     */
     @Override
    public List<Especimen> buscarFotoRecoleccion(Animal animal, Recoleccion recoleccion){
         Session sesion = fabricaSesion.getCurrentSession();
       String hql = "select especimen from Animal animal, Especimen especimen, Recoleccion recoleccion " +
                    "where animal.codigoanimal = :codigo and recoleccion.codigorecoleccion = :recoleccion " +
                    " and animal.codigoanimal = especimen.animal.codigoanimal " +
                     "and especimen.recoleccion.codigorecoleccion = recoleccion.codigorecoleccion";
       
        Query consulta = sesion.createQuery(hql);
        consulta.setParameter("codigo", animal.getCodigoanimal());
        consulta.setParameter( "recoleccion", recoleccion.getCodigorecoleccion());
        List<Especimen> especimenes = consulta.list();
          
        return especimenes;
    }
}
